-
Notifications
You must be signed in to change notification settings - Fork 31
Implement Bloch Sphere rendering #472
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #472 +/- ##
==========================================
- Coverage 94.37% 93.67% -0.70%
==========================================
Files 50 50
Lines 3162 3414 +252
==========================================
+ Hits 2984 3198 +214
- Misses 178 216 +38 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
|
Hi @Fe-r-oz, thank you for contributing! I will give a look more in detail later. For the moment just a few comments. Could you try to reduce the number of lines representing the sphere, and also make more opacity? If I see the qutip version there is probably more transparency and less lines
Also, in your 5th figure, the arch is not an arc. Finally, I don't think we need the Latexstrings and Colors dependencies, as they should be directly implemented in Makie.jl |
|
Thank you, just a few other things before checking the code. The sphere seems to be rotated compared to the one of QuTiP. Indeed, in QuTiP we have that x points almost outside, while here it is -y doing so. Better to align to QuTiP. Since you added the The vectors tips seem to go outside the sphere. Better to show all the examples showed in the qutip documentation, in order to check all the properties. |
|
Thank you very much for your comments and suggestions! Turning it to draft to incorporate all the suggested changes. |
|
Some basic plots from qutip documentation. Empty Sphere: Adding a point and vector to the above figure: code for lines, arc and vectors Adding states from QuantumToolbox Adding scatter of points: Arc, Lines and Vectors Add Quantum States |
| | [`plot_wigner`](@ref) | [Wigner quasipropability distribution](https://en.wikipedia.org/wiki/Wigner_quasiprobability_distribution) | | ||
| | [`plot_fock_distribution`](@ref) | [Fock state](https://en.wikipedia.org/wiki/Fock_state) distribution | | ||
| | [`plot_fock_distribution`](@ref) | [Fock state](https://en.wikipedia.org/wiki/Fock_state) distribution | | ||
| | [`plot_bloch`](@ref) | [Qutip's Plotting on the Bloch Sphere](https://qutip.readthedocs.io/en/stable/guide/guide-bloch.html) | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would remove Qutip. Just "Plotting on the Bloch Sphere"
| ```@setup Bloch_sphere_rendering | ||
| using QuantumToolbox | ||
| using Makie |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Your don't need to import also Makie. CairoMakie is enough.
|
|
||
| When studying the dynamics of a two-level system, it's often convenient to visualize the state of the system by plotting the state vector or density matrix on the Bloch sphere. | ||
|
|
||
| In [QuantumToolbox.jl](https://qutip.org/QuantumToolbox.jl/), this can be done using the [`Bloch`](@ref) or [`plot_bloch`](@ref) methods that provide same syntax as [QuTiP](https://github.com/qutip/qutip). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe directly link to the Bloch Sphere page in qutip
https://qutip.readthedocs.io/en/stable/guide/guide-bloch.html
ext/QuantumToolboxMakieExt.jl
Outdated
|
|
||
| using QuantumToolbox | ||
| using LinearAlgebra | ||
| using Makie |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Better to import only the necessary functions, if they are not a lot.
ext/QuantumToolboxMakieExt.jl
Outdated
| function QuantumToolbox.add_line!( | ||
| b::QuantumToolbox.Bloch, | ||
| start::QuantumObject{<:Union{Ket,Bra,Operator}}, | ||
| endp::QuantumObject{<:Union{Ket,Bra,Operator}}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
endp is not a nice name. Better end or change both to start_point and end_point.
ext/QuantumToolboxMakieExt.jl
Outdated
| b.fig = fig | ||
| b.ax = Makie.Axis3( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Even if the equivalent qutip class embeds also the fig and ax objects. I think that they are not needed in the Bloch struct. render would just generate fig and ax, without storing the in the Bloch object.
ext/QuantumToolboxMakieExt.jl
Outdated
| location[] = b.ax | ||
| end | ||
| end | ||
| Makie.empty!(b.ax) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a few things here.
The code is quite long. I would first write some explanation comments, and divide each operation as a separate function.
Moreover, it is not necessary to repeat Makie.functionnif the function is imported with using Makie: function
src/visualization.jl
Outdated
| frame_color::String | ||
| frame_width::Int | ||
| point_default_color::Vector{String} | ||
| point_color::Vector{Any} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would avoid to use Any, as it makes type instabilities.
src/visualization.jl
Outdated
| fig::Any | ||
| ax::Any |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As I said before. fig and ax are not necessary to be stored in the Bloch structure. Once one calls render, they are generated and the user can operate on them.
src/visualization.jl
Outdated
| fig::Any | ||
| ax::Any | ||
|
|
||
| function Bloch() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of defining this function, I would use Base.@kwdef`
|
Hi @Fe-r-oz, thank you. I have wrote some comments on the code. I have a few minor ones, which I will do after you apply these changes. Anyhow, I see that now the arrows are too short. Isn't it? |
Co-authored-by: Alberto Mercurio <[email protected]>
43fbcf3 to
5b8c30a
Compare
|
Tell me when it is ready for review |
|
Thank you so very much for your guidance!! Please help review this PR, Thank you!! I have hopefully incorporated all of the suggestions! Indeed, the vector size was approx 80% of unit radius, made it 90% of the radius, added LaTex based labelling of axes! Looking forward the the next round of comments! |
| """ | ||
| function _draw_reference_circles(ax) | ||
| wire_color = RGBAf(0.5, 0.5, 0.5, 0.4) | ||
| φ = range(0, 2π, length = 100) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
By dividing into functions helped me a lot on the readability. What happens if we reduce the length of φ for example to 10? Do we reduce the number of circles? If so, then I prefer to have less circles, as said a few comments ago. Could you plot an example here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for your patience and for raising this important point again. Sorry for the delay in addressing this suggestion properly. Regarding the implementation, it appears that Makie.GeometryBasics.Sphere (center + radius) wasn’t suitable for our needs, so I’ve built a custom sphere via surface! instead. Please let me know your feedback!!
The previous approach:
when φ = 10

The new approach:
Edit: Temporarily using this color scheme as the default.
Since we are using surface!, lighter tones combined with transparency may reveal the underlying mesh grid of the surface!.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How did you generate the sphere with the other approach? Could the mesh! function together with Sphere work?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I generated the sphere using a custom parametric mesh via the surface! function, rather than relying on the built-in Sphere type with mesh!. This approach gives us precise control over the number and placement of longitude and latitude lines. The sphere is explicitly constructed from parametric equations in spherical coordinates.
While Makie’s Sphere type (an alias for HyperSphere{3, T}) is convenient for basic 3D geometry, it has certain design constraints. For example, mesh generation is fixed internally using coordinates(s::Sphere, nvertices=24), which samples spherical angles using a hardcoded resolution. Unfortunately, it appears that nvertices isn't configurable through the mesh! interface. I also explored modifying the Sphere's mesh parameters directly, but it seems this flexibility isn’t currently exposed through the high-level API.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But can't you play with transparency and alpha on the mesh? What I don't like of this surface method is that I can see the underlying mesh grid.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can indeed tweak the alpha and transparency settings to reduce or eliminate the appearance of the mesh grid when using surface!. The last two examples I shared earlier were mostly exploratory, just to get a feel for different visual effects while playing with color and opacity settings. I also don't like the underlying grid look which was likely caused by the alpha and transparency settings.
For example, tweaking alpha and transparency settings, we get:
Edit: increasing the resolution, the mesh grid disappears. Some examples;
We can refine this method further; I will explore additional tweaks and see how to achieve a cleaner result with surface! Please let me know your feedback! Thank you!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the first image is really nice. How did you get that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you! There are two ways of generating the first image. We can use both sphere + mesh or surface!. I generated the above images via surface!. But I have been following through your comment and as you mentioned, we can do the same with sphere+mesh (figure attached below). The goal is to disappear the mesh grid, and draw the few latitude and longitude lines ourselves.
Edit: more polished version
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I like it. This could be the definitive one.
ext/QuantumToolboxMakieExt.jl
Outdated
| ([Point3f(0, -1.01, 0), Point3f(0, 1.01, 0)], "y"), # Y-axis | ||
| ([Point3f(-1.01, 0, 0), Point3f(1.01, 0, 0)], "x"), # X-axis | ||
| ([Point3f(0, 0, -1.01), Point3f(0, 0, 1.01)], "z"), # Z-axis |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why 1.01 and not simply 1.0? You can send some examples here in case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In general, they are also not aligned to the axes. They should be the continuation of the corresponding axis
ext/QuantumToolboxMakieExt.jl
Outdated
| _draw_bloch_sphere(ax) | ||
| _draw_reference_circles(ax) | ||
| _draw_axes(ax) | ||
| _plot_points(b, ax) | ||
| _plot_lines(b, ax) | ||
| _plot_arcs(b, ax) | ||
| _plot_vectors(b, ax) | ||
| _add_labels(ax) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fantastic, thanks. Could you just add the ! symbol to tell this converts ax inplace?
ext/QuantumToolboxMakieExt.jl
Outdated
| (Point3f(1.04, 0, 0), L"\textbf{y}"), | ||
| (Point3f(0, -1.10, 0), L"\textbf{x}"), | ||
| (Point3f(0, 0, -1.10), L"\mathbf{|1\rangle}"), | ||
| (Point3f(0, 0, 1.08), L"\mathbf{|0\rangle}"), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The labels are a bit too close to the figure. Could you move them out a bit? Also, why y and x are textbf while in the other we have mathbf?
src/visualization.jl
Outdated
| """Vectors to plot on the Bloch sphere""" | ||
| vectors::Vector{Vector{Float64}} = Vector{Vector{Float64}}() | ||
| """Lines to draw on the sphere (points, style, properties)""" | ||
| lines::Vector{Tuple{Vector{Vector{Float64}},String,Dict{Symbol,Any}}} = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we have Dict{Symbol, Any}? Can't we infer the type?
ext/QuantumToolboxMakieExt.jl
Outdated
| Creates a semi-transparent spherical surface at the origin with radius 1. | ||
| """ | ||
| function _draw_bloch_sphere(ax) | ||
| sphere_color = RGBAf(1.0, 0.86, 0.86, 0.2) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the Bloch structure we have defined the sphere_alpha field. But it seems to not been used here. Am I wrong?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In general, let's check that we use all the fields of Bloch.
| fig = Figure() | ||
| pos = fig[2, 3] | ||
| fig1, ax = @test_logs (:warn,) plot_fock_distribution(ψ * 2; library = Val(:Makie), location = pos) | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
They are quite a lot, which is nice, but can you embed them inside a @testset?
Co-authored-by: Alberto Mercurio <[email protected]>
|
I was also thinking, could you also test it with GLMakie instead of CairoMakie? This should be done without any change, as we support Makie in general. I'm curious to see if the rendering quality is the same and what happens in the interactive windows, since now we can move interactively |
|
Really nice! Let's wait the runtests. There are already some failing like spell check and changelog. For the changelog, you can do it by updating the Changelo.md file and then running The documentation test is still running, but I remember that it was failing. Alway check all the tests with |
|
Thank you very much for your guidance! I will make sure that all the tests pass! |
|
I did |
Co-authored-by: Yi-Te Huang <[email protected]>
Co-authored-by: Yi-Te Huang <[email protected]>
|
Ok, thank you for your hard work. |


























Checklist
Thank you for contributing to
QuantumToolbox.jl! Please make sure you have finished the following tasks before opening the PR.make test.juliaformatted by running:make format.docs/folder) related to code changes were updated and able to build locally by running:make docs. PS. make docs crashes my PC after it's ran for some time but I made sure to add the necessary documentation.CHANGELOG.mdshould be updated (regarding to the code changes) and built by running:make changelog.Request for a review after you have completed all the tasks. If you have not finished them all, you can also open a Draft Pull Request to let the others know this on-going work.
Description
Edit: This PR fixes #461. The goal is to add the bloch rendering in Julia which have a similar user experience as qutip
Additional context
Edit: Attaching the plots that reproduce the entire qutip documentation documentation:
Add a Single Data Point
Add a Single Vector
Add Arc, Line, and Vector
Add Multiple Points
We can also use
GLMakie